Function FormatarData(aData : string) : String;
begin
  Result := Format('%s/%s/%s', [Copy(aData, 9, 2), Copy(aData, 6, 2), Copy(aData, 0, 4)]);
end;

Function FieldValue(aDataSet,aCampo:String):TField;
begin
	Result := DataSets.GetDataSetByName(aDataSet).FieldByName(aCampo)
end;

function FindDataSet(aName : String) : TSpdXSDClientDataSet;
begin
	result := DataSets.GetDataSetByName(aName);
end;

function GetAno(aXMLDate : String) : Word;
begin
	Result := StrToInt(Copy(aXmlDate,1,4));
end;

function GetMes(aXMLDate : String) : Word;
begin
	Result := StrToInt(Copy(aXmlDate,6,2));
end;

function GetDia(aXMLDate : String) : Word;
begin
	Result := StrToInt(Copy(aXmlDate,9,2));
end;

Function XmlDateToDateTime(aXmlDate : String) : TDateTime;
begin
  Result := EncodeDate(GetAno(aXmlDate), GetMes(aXmlDate), GetDia(aXmlDate));
end;

Function BetweenDateTime(aData, aInicio, aFim : String) : boolean;
var
  _data : TDateTime;
begin
  _data := StrToDate(aData);
  Result := ((_data >= StrToDate(aInicio)) AND (_data <= StrToDate(aFim)));
end;

function EstaNaListaDeExcecoes(aCodigoMun : string) : boolean;
	begin
		case StrToInt(aCodigoMun) of
		 4305871, 2101919, 2202251,
		 2201988, 2611533, 3117836,
		 3152131, 5203939, 5203962 : result := true;
		else
		  result := false;
		end;
	end;

Function CalcDigVerificadorCodMunicipio(Const aCodigoMun : string) : string;
var
  i, _peso, _DV, _somaPond, _pond : integer;
begin
  _somaPond := 0;
  _peso := 1;
  for i := 1 to Length(aCodigoMun) do
  begin
    _pond := StrToInt(Copy(aCodigoMun,i,1)) * _peso;

    if _pond > 9 then
       _pond := StrToInt( Copy(IntToStr(_pond), 1,1)) + StrToInt( Copy(IntToStr(_pond), 2,1));

    _somaPond := _somaPond + (_pond);
    if _peso = 1 then
       _peso := 2
    else
       _peso := 1;

  end;

  if (_somaPond mod 10) = 0 then
    _DV := 0
  else
    _DV := 10 - (_somaPond mod 10);
  Result := IntToStr(_DV);

end;

Function ValidaCodigoMunicipio(Const aCodigoMun : string) : Boolean;
begin
  if EstaNaListaDeExcecoes(aCodigoMun) then
     result := true
  else
	 result := CalcDigVerificadorCodMunicipio(Copy(aCodigoMun,1,6)) = Copy(aCodigoMun,7,1);
end;

function DupeString(const AText : String; const ACount : Integer) : String;
var
	i : integer;
begin
	result := '';
	for i := 0 to ACount do
		result := result + AText;
end;

function BuscaCaracteresValidos(valor, validos: String): String;
var
  i: integer;
Begin
  result := '';
  for i := 1 to length(Valor) do
    if pos(valor[i], Validos) > 0 then
      result := result + valor[i];
end;

function ValidaCNPJ(Cnpj: String): Boolean;
var
  _nSoma,
  _i,
  _nDigito1,
  _nDigito2 : integer;

begin

  result := false;
  Cnpj := BuscaCaracteresValidos(cnpj, '0123456789');
  if (Length(Trim(Cnpj)) = 14) and (Cnpj <> DupeString('0', 14)) and (Cnpj <> DupeString('1', 14)) and
    (Cnpj <> DupeString('2', 14)) and (Cnpj <> DupeString('3', 14)) and (Cnpj <> DupeString('4', 14)) and
    (Cnpj <> DupeString('5', 14)) and (Cnpj <> DupeString('6', 14)) and (Cnpj <> DupeString('7', 14)) and
    (Cnpj <> DupeString('8', 14)) and (Cnpj <> DupeString('9', 14)) then
	begin
		_nSoma := 0;

		for _i := 1 to 12 do
		  if _i < 5 then
			_nSoma := _nSoma + (StrToint(Copy(Cnpj, _i, 1)) * (6 - _i))
		  else
			_nSoma := _nSoma + (StrToint(Copy(Cnpj, _i, 1)) * (14 - _i));

		_nDigito1 := 11 - (_nSoma Mod 11);

		if _nDigito1 > 9 then
		  _nDigito1 := 0;

		_nSoma := 0;

		for _i := 1 to 13 do
		  if _i < 6 then
			_nSoma := _nSoma + (StrToint(Copy(Cnpj, _i, 1)) * (7 - _i))
		  else
			_nSoma := _nSoma + (StrToint(Copy(Cnpj, _i, 1)) * (15 - _i));

		_nDigito2 := 11 - (_nSoma Mod 11);

		if _nDigito2 > 9 then
		  _nDigito2 := 0;

		if Copy(Trim(Cnpj), 13, 2) = intToStr(_nDigito1) + intToStr(_nDigito2) then
		  Result := true;
	end;
end;


procedure PopulaListaUF(aList: TstringList);
  begin
    aList.Add('AC=12');
    aList.Add('AL=27');
    aList.Add('AP=16');
    aList.Add('AM=13');
    aList.Add('BA=29');
    aList.Add('CE=23');
    aList.Add('DF=53');
    aList.Add('ES=32');
    aList.Add('GO=52');
    aList.Add('MA=21');
    aList.Add('MT=51');
    aList.Add('MS=50');
    aList.Add('MG=31');
    aList.Add('PA=15');
    aList.Add('PB=25');
    aList.Add('PR=41');
    aList.Add('PE=26');
    aList.Add('PI=22');
    aList.Add('RJ=33');
    aList.Add('RN=24');
    aList.Add('RS=43');
    aList.Add('RO=11');
    aList.Add('RR=14');
    aList.Add('SC=42');
    aList.Add('SP=35');
    aList.Add('SE=28');
    aList.Add('TO=17');
  end;

function GetCodeUF(Const aUF : String) : String;
var
  _listUF : TStringList;
begin
  _listUF := TStringList.Create;
  Try
     PopulaListaUF(_listUF);
     Result := _ListUF.Values[aUF];
  Finally
    _listUF.Free;
  End;
end;

function ValidaCPF(aCPF: string): Boolean;
var
  i: Integer;
  Want: Char;
  Wvalid: Boolean;
  Wdigit1, Wdigit2: Integer;

begin
	Wdigit1 := 0;
	Wdigit2 := 0;

	Want := aCPF[1];
	Delete(aCPF, pos('.',aCPF), 1)  //verificar a possivel implicancia em usar 'pos' ao invez de 'ansipos'
	Delete(aCPF, pos('.',aCPF), 1)  //verificar a possivel implicancia em usar 'pos' ao invez de 'ansipos'
	Delete(aCPF, pos('-',aCPF), 1)  //verificar a possivel implicancia em usar 'pos' ao invez de 'ansipos'

	// testar se o cpf é repetido como 111.111.111-11
	for i := 1 to Length(aCPF) do
	begin
		if aCPF[i] <> Want then
		begin
			Wvalid := true; // se o cpf possui um digito diferente ele passou no primeiro teste
			break;
		end;
	  end;

	// se o cpf é composto por numeros repetido retorna falso
	if not Wvalid then
	begin
		Result := False;
		Exit;
	end;

	// executa o calculo para o primeiro verificador
	for i := 1 to 9 do
	begin
		Wdigit1 := Wdigit1 + (StrToInt(aCPF[10 - i]) * (i + 1));
	end;

	Wdigit1 := ((11 - (Wdigit1 mod 11)) mod 11) mod 10;

	{ 	formula do primeiro verificador
		soma=1°*2+2°*3+3°*4.. até 9°*10
		digito1 = 11 - soma mod 11
		se digito > 10 digito1 =0
	}

	// verifica se o 1° digito confere
	if IntToStr(Wdigit1) <> aCPF[10] then
	begin
		Result := False;
		Exit;
	end;

	for I := 1 to 10 do
	begin
		Wdigit2 := Wdigit2 + (StrToInt(aCPF[11 - I]) * (I + 1));
	end;

	Wdigit2 := ((11 - (Wdigit2 mod 11)) mod 11) mod 10;
	{ 	formula do segundo verificador
		soma=1°*2+2°*3+3°*4.. até 10°*11
		digito1 = 11 - soma mod 11
		se digito > 10 digito1 =0
	}

	// confere o 2° digito verificador
	if IntToStr(Wdigit2) <> aCPF[11] then
	begin
		Result := False;
		Exit;
	end;

	// se chegar até aqui o cpf é valido
	Result := true;
end;

{******************* ValidaAutenticidadeDv E Dependencias ************************}

Function CompleteDataEmis(aAAMM : string) : string;
  begin
    result := Format('%s-%s-%s',['20' + Copy(aAAMM,1,2), Copy(aAAMM,3,2), '01']);
  end;

procedure LoadParams(var aAno, aMes,aCNPJ : String);
var
  Agora_: TDateTime;
  Ano_, Mes_, Dia_: Word;
begin
	Agora_ := Now;
	DecodeDate(Agora_, Ano_, Mes_, Dia_);
	aMes := PadC(IntToStr(Mes_), 2,'0',True);
	aAno := Copy(IntToStr(Ano_), 3, 2);
	Try
		StrToInt64(aCNPJ);
	except
		raiseException(Format('O campo CNPJ: %s deve ser um número Inteiro', [aCNPJ]));
	end;
end;

procedure Checkparams(var aCodigo,aTpEmis,aDtEmissao,aUF,aCNPJ,aModelo,aNRNota,aCodigo : String);
  begin
    if length(aCodigo) > 8 then
      raiseException(Format('O Código da nota(cNF) "%s", excede o máximo de 8 dígitos (Manual 4.01)',[aCodigo]));

    if length(atpEmis) <> 1 then
      raiseException(Format('O valor do tipo de emissão(tpEmis) "%s" é inesperado.',[aCodigo]));

    if Length(aDtEmissao) <> 10 then
      raiseException(Format('%s Data de Emissão no Formato inválido. Utilizar YYYY-MM-DD', [aDtEmissao]));

    if (aUF = '') or (aCNPJ = '') or (aModelo = '') or
       (aNRNota = '') or (aCodigo = '') or (aTpEmis = '') then
      raiseException(Format
        ('Os Campos: Código da UF Emitente =  %s' + #13 +
          'CNPJ do Emitente = %s ' + #13 +
          'Código do Modelo do Documento Fiscal = %s ' + #13 +
          'Número da Nota Fiscal = %s' + #13 +
          'Tipo de emissão = %s' + #13 +
          'Código (controle do sistema) Nota Fiscal = %s' + #13 +
          'são campos obrigatórios para o cálculo do dígito verificador.',
        [aUF, aCNPJ, aModelo, aNRNota, aTpEmis, aCodigo]));
  end;


Function DigVerificador(aValor: String; aBase: integer; aResto: boolean): string;
var
  _Soma: integer;
  _Contador, _Peso, _Digito: integer;
begin

  _Soma := 0;
  _Peso := 2;
  for _Contador := Length(aValor) downto 1 do
  begin
    _Soma := _Soma + (StrToInt(aValor[_Contador]) * _Peso);
    if _Peso < aBase then
      _Peso := _Peso + 1
    else
      _Peso := 2;
  end;

  if aResto then
    Result := IntToStr(_Soma mod 11)
  else
  begin
    _Digito := 11 - (_Soma mod 11);
    if (_Digito > 9) then
      _Digito := 0;
    Result := IntToStr(_Digito);
  end

end;



  function CalculaDV(const aAno,aMes,aUF,aCNPJ,aModelo,aSerie,aNRNota,atpEmis,aCodigo:String) : string;
  begin
    result := DigVerificador(PadC(aUF, 2,'0',True) +
                             aAno +
                             aMes +
                             aCNPJ +
                             aModelo +
                             PadC(aSerie, 3,'0',True) +
                             PadC(aNRNota, 9,'0',True) +
                             atpEmis +
                             PadC(aCodigo, 8,'0',True),9,false);
  end;

function CalculaChaveVm40(const aDtEmissao, aUF, aCNPJ, aModelo, aSerie, aNRNota, aTpEmis, aCodigo: String): String;
var
  Mes, Ano, DV, tpEmis : String;
  begin
  Result := '';

  LoadParams(Ano, Mes,aCNPJ);
  TpEmis := aTpEmis;
  CheckParams(aCodigo,tpEmis,aDtEmissao,aUF,aCNPJ,aModelo,aNRNota,aCodigo);

  Mes := Copy(aDtEmissao, 6, 2);
  Ano := Copy(aDtEmissao, 3, 2);
  DV  := CalculaDV(Ano,Mes,aUF,aCNPJ,aModelo,aSerie,aNRNota,tpEmis,aCodigo);

  Result := (PadC(aUF, 2,'0',True) + Ano + Mes + aCNPJ + aModelo + PadC(aSerie, 3,'0',True)) + PadC (aNRNota, 9,'0',True) + tpEmis + PadC(aCodigo, 8,'0',True) + DV;

  // Result:=aChave;

end;

function CalculaChaveVm30(aDtEmissao, aUF, aCNPJ, aModelo, aSerie, aNRNota, aCodigo: String): String;
var
  Agora_: TDateTime;
  Ano_, Mes_, Dia_: Word;
  Mes, Ano, DV: String;

begin
  Result := '';
  Agora_ := Now;
  DecodeDate(Agora_, Ano_, Mes_, Dia_);
  Mes := PadC(IntToStr(Mes_), 2,'0',True);
  Ano := Copy(IntToStr(Ano_), 3, 2);

  Mes := Copy(aDtEmissao, 6, 2);
  Ano := Copy(aDtEmissao, 3, 2);

  if Length(aDtEmissao) <> 10 then
    raiseException(Format(
      '%s Data de Emissão no Formato inválido. Utilizar YYYY-MM-DD',
      [aDtEmissao]));

  if (aUF = '') or (aCNPJ = '') or (aModelo = '') or (aNRNota = '') or
    (aCodigo = '') then
    RaiseException(Format('Os Campos: Código da UF Emitente =  %s' + #13 +
        'CNPJ do Emitente = %s ' + #13 +
        'Código do Modelo do Documento Fiscal = %s ' + #13 +
        'Número da Nota Fiscal = %s' + #13 +
        'Código (controle do sistema) Nota Fiscal = %s' + #13 +
        'são campos obrigatórios para o cálculo do dígito verificador.',
      [aUF, aCNPJ, aModelo, aNRNota, aCodigo]));

  Try
    StrToInt64(aCNPJ);
  except
    RaiseException(Format(
      'O campo CNPJ: %s deve ser um número Inteiro', [aCNPJ]));
  end;

  DV := DigVerificador(PadC(aUF, 2,'0',True) + Ano + Mes + aCNPJ + aModelo + PadC(aSerie, 3,'0',True) + PadC(aNRNota, 9,'0',True) + PadC(aCodigo, 9,'0',True),9,False);
  Result := (PadC(aUF, 2,'0',True) + Ano + Mes + aCNPJ + aModelo + PadC(aSerie, 3,'0',True) + PadC(aNRNota, 9,'0',True) + PadC(aCodigo, 9,'0',True)) + DV;

end;

function DecodeChave (Const aChave : string; aVersaoManual : String) : TspdDecodeChaveNFe;
begin
  if Length(aChave) <> 44 then
	RaiseException(Format('A Chave da NFe %s deve possuir exatamente 44 dígitos.',[aChave]));

  Result.cUF := Copy(aChave,1,2);
  result.AAMM := Copy(aChave,3,4);
  result.CNPJ := Copy(aChave,7,14);
  result.Modelo := Copy(aChave,21,2);
  result.Serie := Copy(aChave,23,3);
  result.nNF := Copy(aChave,26,9);
  result.cDV := Copy(aChave,44,1);

  case aVersaoManual of
   'vm202a',
   'vm30'   : begin
              result.tpEmis := '';
              result.cNF := Copy(aChave,35,9);
            end;
   'vm40',
   'vm50',
   'vm50a'  : begin
              result.tpEmis := Copy(aChave,35,1);
              result.cNF := Copy(aChave,36,8);
            end;
  else
    RaiseException('Versão de Manual não suportada para decodificação.');
  end;
end;


Function ValidaAutenticidadeDV(Const aChave : String; aVersaoManual : String) :Boolean;
Var
  _Dc : TspdDecodeChaveNFe;
  _NewChave : string;
begin
  result := false;
  _Dc := DecodeChave(aChave,aVersaoManual);
  case aVersaoManual of
   'vm202a',
   'vm30' : _NewChave := CalculaChavevm30(CompleteDataEmis(_Dc.AAMM), _Dc.cUF, _dc.CNPJ, _dc.Modelo, _dc.Serie, _Dc.nNF, _dc.cNF);
   'vm40',
   'vm50',
   'vm50a' : _NewChave := CalculaChavevm40(CompleteDataEmis(_Dc.AAMM), _Dc.cUF, _dc.CNPJ, _dc.Modelo, _dc.Serie, _Dc.nNF, _Dc.tpEmis, _dc.cNF);
  end;

  if Copy(_NewChave,44,1) = _Dc.cDV then
     result := true;
end;


Function ValidaAutenticidadeDVCamposXML(Const aChaveNota, aDtEmi, aCUF, aCNPJ, aModelo, aSerie, aNNF, aTpEmis, aCNF : String; aVersaoManual : String) :Boolean;
Var  
  _NewChave : string;
begin
  result := false;
    case aVersaoManual of
   'vm202a',
   'vm30' : _NewChave := CalculaChavevm30(aDtEmi, aCUF, aCNPJ, aModelo, aSerie, aNNF, aCNF);
   'vm40',
   'vm50',
   'vm50a' : _NewChave := CalculaChavevm40(aDtEmi, aCUF, aCNPJ, aModelo, aSerie, aNNF, aTpEmis, aCNF);
  end;

  if Copy(_NewChave,44,1) = Copy(aChaveNota,44,1) then
     result := true;	
end;

{***** Função que valida Regra GD01  *****}

function ExisteAvulsa : Boolean;
begin
	Result := False;
	if (FieldValue('NFe','CNPJ_D02').AsString <>'') or (FieldValue('NFe','xOrgao_D03').AsString <>'') or
	(FieldValue('NFe', 'matr_D04').AsString <>'') or (FieldValue('NFe','xAgente_D05').AsString <>'') or
	(FieldValue('NFe','fone_D06').AsString <>'') or (FieldValue('NFe','UF_D07').AsString <>'') or
	(FieldValue('NFe','nDAR_D08').AsString <>'') or (FieldValue('NFe','dEmi_D09').AsString <>'') or
	(FieldValue('NFe','vDAR_D10').AsString <>'') or (FieldValue('NFe','repEmi_D11').AsString <>'') or
	(FieldValue('NFe','dPag_D12').AsString <>'') then
		Result:= True;
end;

{**** Função que valida Regra GU01 ****** }
function PossuiISSQN (aDataSet : TDataSet): Boolean;
begin
	Result := False;

	if (aDataSet.FieldByName('vBC_U02').AsString <>'') or (aDataSet.FieldByName('vAliq_U03').AsString <>'') or
	(aDataSet.FieldByName( 'vISSQN_U04').AsString <>'') or (aDataSet.FieldByName('cMunFG_U05').AsString <>'') or
	(aDataSet.FieldByName('cListServ_U06').AsString <>'') then
		Result:= True;
end;



Function CompareComTolerancia(Const aValue1, aValue2, aTolerancia : Extended) : Boolean;
begin
  result := false;
  if ((aValue1 >= (aValue2 - aTolerancia)) and (aValue1 <= (aValue2 + aTolerancia))) then
   result := true;
end;


function VerificaZeroEAN(const aEAN: String): Boolean;
var
  i: integer;
begin
  result := True;
  for i := 1 to Length(aEAN) do
	if copy(aEAN,i,1) <> '0' then
	begin
	  result := False;
	  exit;
	end;
end;

{ *** Fim função validaean ***}
Function ValidaDvEAN(codigo : string) : boolean;
var
  var1,
  var2,
  total,
  aux,
  i : Integer;

begin

  var1 := 0;
  var2 := 0;

	case Length(Trim(codigo)) of
	8,12,13,14:
		begin
			while length(codigo) <14 do
				codigo := '0' + codigo;

			for i:=1 to (length(codigo)-1) div 2 do
			begin
				var1 := var1 + (3 * StrToInt(codigo[(2*i)-1]));
				var2 := var2 + (1 * StrToInt(codigo[(2*i)]));
			end;

			var1 := var1 + (3 * StrToInt(codigo[13]));

			total := var1 + var2;

			aux := total mod 10;

			aux := 10 - aux;

			if aux = 10 then
				aux := 0;

			if IntToStr(aux) = codigo[Length(codigo)]
				then result := true
				else result := false;
		end;
	0: result := True;
	else
		result := False;
	end;
end;

function SomenteZeros(aText : String) : boolean;
var
  _i : integer;
begin
  result := True;
  for _i:=0 to length(aText) do
	if Copy(Trim(aText),_i,1) <> '0' then
		result := False;
end;

function PosStr(SubTexto, Texto: Widestring): Integer;
begin
  Result := pos(SubTexto, Texto);
end;

Function GetValueTag(aTag, aTxt: String): String;
Var
  aPINI, aPFIN: integer;
begin
  aPINI := PosStr('<' + aTag + '>', aTxt) + (Length(aTag) + 2);
  aPFIN := PosStr('</' + aTag + '>', aTxt);
  Result := Copy(aTxt, aPINI, aPFIN - aPINI);
end;

procedure AdicionarAlerta(var aLista : TstringList; const aMSG,aItem : string);
var
  _list : TstringList;
	i : integer;
begin
	_list := TstringList.Create;
	try
		if Trim(aMSG) <> '' then
		begin
			_list.text := Trim(aMSG);
			for i := 0 to _list.count-1 do
			begin
				aLista.Add('Alerta[CSTCFOP]: Item '+aItem+': '+_list.strings[i]);
			end;
		end;
	finally
	  _list.Free;
	end;
end;

procedure AdicionarAlertaICMS(var aLista : TstringList; const aMSG,aItem : string);
var
  _list : TstringList;
	i : integer;
begin
	_list := TstringList.Create;
	try
		if Trim(aMSG) <> '' then
		begin
			_list.text := Trim(aMSG);
			for i := 0 to _list.count-1 do
			begin
				aLista.Add('Alerta[ICMSUFDEST]: Item '+aItem+': '+_list.strings[i]);
			end;
		end;
	finally
	  _list.Free;
	end;
end;

function ContaVirgula(aFrase: string): integer;
var
  i, ivtot: Integer;
begin
  ivTot := 0;
  aFrase := Trim(aFrase);
  for i := 1 to Length(aFrase) do
  begin
    if (aFrase[i] = ',') then
      inc(ivTot);
  end;
  Result := ivTot;
end;

function ExisteEm(aValorProcurado, aLista: string): boolean;
var
  _delimitpos, j, QtdeLista: integer;
  _ValorVerificado: string;
begin
  Result := False;
  QtdeLista := ContaVirgula(aLista);
  for j := 0 to QtdeLista do
  begin
	_delimitpos := Pos(',',aLista);
    if _delimitpos > 0 then
      _ValorVerificado := Copy(aLista,1,_delimitpos - 1)
	else
      _ValorVerificado := aLista;
    if aValorProcurado = _ValorVerificado then
      Result := True;
	aLista := StringReplace(aLista,_ValorVerificado + ',','',[]);
  end;
end;


function getPrimeiroDigito(const aText : string) : string;
begin
  Result := Copy(aText,1,1);
end;

function FormatFloat(const aFloat: extended) : string;
var
	_posPonto : integer;
begin
	Result := FloatTostr(aFloat);
	_posPonto := Pos('.',Result);
	Result := Copy(Result, 0, _posPonto + 2);
end;

Function ConcatenarValorTotal(aCampo, aValorInformado : string; aValorCalculado: Extended) : string;
var
	_valorCalculado : string;
begin
	_valorCalculado := FormatFloat(aValorCalculado);
	if aValorInformado = '' then
		aValorInformado := 'Não Informado';
	Result := Format('(%s informado: %s, %s calculado: %s)', [aCampo,aValorInformado,aCampo,_valorCalculado]);
end;

Function ConcatenarNumItem(aNumItem : string) : string;
begin	
  result := Format(' [nItem:%s]',[aNumItem]); 
end;

function GetAliquotaPorEstado(const aEstadoOrigem, aEstadoDestino : string) : string;
var
	_ini : TspdIniFile;
begin
	_ini := TspdIniFile.Create(Params.Values['TabelaAliquotaPorEstado']);
	try
		Result :=  _ini.ReadString(UpperCase(aEstadoOrigem),UpperCase(aEstadoDestino),'');
	finally
		_ini.free;
	end;
end;

Function GetExtend(Const aValue : string) : Extended;
begin
  if (aValue <> '') then
    result := StrToFloat(aValue)
  else
    result := 0;
end;

function CFOPdeDevolucao(const aCFOP: string): boolean;
begin
  Result := ExisteEm(aCFOP, '1201,1202,1203,1204,1208,1209,1410,1411,1503,1504,1553,' +
                            '1660,1661,1662,1918,2201,2202,2203,2204,2208,2209,' +
                            '2410,2411,2503,2504,2553,2660,2661,2662,2918,3201,' +
                            '3202,3211,3503,3553,5201,5202,5208,5209,5210,5410,5411,' +
                            '5412,5413,5503,5553,5555,5556,5660,5661,5662,5918,6201,' +
                            '6202,6208,6209,6210,6410,6411,6412,6413,6503,6553,6555,' +
                            '6556,6660,6661,6662,6918,7201,7202,7210,7211,7553,7556');
end;

function GeraDV(aStr: string): string;
var
  Soma,I,J: Integer;
begin
  J := 1;
  Soma := 0;
  for I := Length(aStr) downto 1 do
  begin
    Soma := Soma + StrToInt(aStr[i]) * J;
    Inc(J);
  end;
  Result := IntToStr(11 - (Soma mod 11));
end;

function GeraDVRecopi(aRecopi: string): string;
var
  DV1, DV2: string;
begin
  DV1 := GeraDV(aRecopi);
  DV2 := GeraDV(aRecopi + DV1);
  Result := DV1 + DV2;
end;

function ValidaRecopi(aRecopi: string): boolean;
var
  _RegexList: TStringList;
  DV: string;
begin
  Result := False;
  _RegexList := TStringList.Create;
  try
    _RegexList.Add('^(1|2)[0-9]{3}(0[1-9]|1[0-2])((0[1-9])|((1|2)[0-9])|3(0|1))((0|1)[0-9]|2[0-3])([0-5][0-9])([0-5][0-9])[0-9]{4}[0-9]{2}$');
    if ReconhecerPadrao(aRecopi, _RegexList) <> -1 then
    begin
      DV := aRecopi[10] + aRecopi[11];
      if GeraDVRecopi(aRecopi) = DV then
        Result := True;
    end;
  finally
    _RegexList.Free;
  end;
end;

function ExisteExportacao(aItemDS: TDataSet) : Boolean;
begin
  Result := False;
  if (aItemDS.FieldByName('nDraw_I51').AsString <> '') or
     (aItemDS.FieldByName('nRE_I53').AsString <> '') or
     (aItemDS.FieldByName('chNFe_I54').AsString <> '') or
     (aItemDS.FieldByName('qExport_I55').AsString <> '') then
    Result:= True;
end;

function NCMdePapel(const aNCM: string): boolean;
begin
  Result := ExisteEm(aNCM,
    '48010010,48010090,48021000,48022010,48022090,48024010,48024090,48025410,'+
    '48025491,48025499,48025510,48025591,48025592,48025599,48025610,48025692,'+
    '48025693,48025699,48025710,48025792,48025793,48025799,48025810,48025891,'+
    '48025892,48025899,48026110,48026191,48026192,48026199,48026210,48026291,'+
    '48026292,48026299,48026910,48026991,48026992,48026999,48041100,48041900,'+
    '48042100,48042900,48043110,48043190,48043910,48043990,48044100,48044200,'+
    '48044900,48045100,48045200,48045910,48045990,48051100,48051200,48051900,'+
    '48052400,48052500,48053000,48054010,48054090,48055000,48059100,48059210,'+
    '48059290,48059300,48061000,48062000,48063000,48064000,48070000,48081000,'+
    '48082000,48083000,48089000,48101310,48101381,48101382,48101389,48101390,'+
    '48101410,48101481,48101482,48101489,48101490,48101910,48101981,48101982,'+
    '48101989,48101990,48102210,48102290,48102910,48102990,48103110,48103190,'+
    '48103210,48103290,48103910,48103990,48109210,48109290,48109910,48109990,'+
    '48111010,48111090,48114110,48114190,48114910,48114990,48115110,48115121,'+
    '48115122,48115123,48115129,48115130,48115910,48115921,48115922,48115923,'+
    '48115929,48115930,48116010,48116090,48119010,48119090,48239091,48239099');
end;

function ValidarCenq(aCenq : string) : boolean;
begin
   Result := ExisteEm(aCenq,
      '001,002,003,004,005,006,007,101,102,103,104,105,106,107,108,109,110,111,'+
      '112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,'+
      '130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,'+
      '148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,301,302,303,'+
      '304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,'+
      '322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,'+
      '340,341,342,343,344,345,346,347,348,349,350,351,601,602,603,604,605,606,'+
      '607,608,999');
end;